import asyncio

from langchain_core.messages import AIMessage, HumanMessage
from langchain_core.prompts import ChatPromptTemplate, HumanMessagePromptTemplate, MessagesPlaceholder

# 演示异步方法不能在jupyterlab中。

### 测试1 基础异步格式化（无变量冲突）
# 1. 定义含变量的异步模板
template = ChatPromptTemplate(
    [
        ("system", "你是{role}，回复不超过2句话。"),  # 系统消息（含变量）
        HumanMessagePromptTemplate.from_template(
            "我要{action}{target}，能帮我吗？"
        ),  # 消息模板
        AIMessage(content="没问题！我来协助你～"),  # 固定 AIMessage
    ]
)


# 2. 异步调用 aformat_messages
async def test_basic():
    print("=== 示例1：基础异步格式化 ===")
    # 传入变量
    messages = await template.aformat_messages(
        role="旅行规划师", action="规划", target="云南3日游"
    )
    # Debug 关键：打印格式化后的消息（验证变量替换+类型）
    for i, msg in enumerate(messages):
        print(f"  消息{i+1}：{type(msg).__name__} -> {msg.content}")

### 测试2 含可选占位符的异步格式化
# 1. 定义含可选占位符的模板
template = ChatPromptTemplate([
    ("system", "你是客服，优先回应历史问题。"),
    MessagesPlaceholder(variable_name="chat_history", optional=True),  # 可选历史
    ("human", "现在能解决我的{current_question}吗？"),
])

# 2. 异步测试：传/不传可选变量
async def test_optional_placeholder():
    print("\n=== 示例2：含可选占位符 ===")
    
    # 场景1：不传 chat_history（用默认空列表）
    print("场景1：不传可选变量：")
    messages1 = await template.aformat_messages(current_question="订单退款")
    for i, msg in enumerate(messages1):
        print(f"  {i+1}. {type(msg).__name__} -> {msg.content}")
    
    # 场景2：传入 chat_history（带历史对话）
    print("\n场景2：传入可选变量：")
    messages2 = await template.aformat_messages(
        current_question="订单退款",
        chat_history=[
            ("human", "我的订单号是123456"),
            ("ai", "已记录你的订单号，请问有什么问题？")
        ]
    )
    for i, msg in enumerate(messages2):
        print(f"  {i+1}. {type(msg).__name__} -> {msg.content}")

### 测试3 变量缺失 / 类型错误 → Debug 异常场景

# 1. 定义含多个变量的模板
template = ChatPromptTemplate([
    ("system", "你是{profession}，计算{num1}和{num2}的{operation}。"),
    ("human", "结果是多少？"),
])

# 2. 异步测试：变量缺失/类型错误
async def test_error_cases():
    print("\n=== 示例3：异常场景测试 ===")
    
    # 场景1：缺少必填变量（num2）
    try:
        await template.aformat_messages(
            profession="数学家",
            num1=10,
            operation="加法"  # 少传 num2
        )
    except Exception as e:
        print(f"场景1 报错（预期）：{e}")  # 提示缺少变量 'num2'
    
    # 场景2：变量类型错误（num1 传字符串）
    try:
        await template.aformat_messages(
            profession="数学家",
            num1="十",  # 应传数字，却传字符串
            num2=20,
            operation="加法"
        )
    except Exception as e:
        print(f"场景2 报错（预期）：{e}")  # 若模板无类型限制，可能不报错，但结果不符合预期
        # 解决：用 input_types 限制变量类型（如下）
        template_with_types = ChatPromptTemplate(
            [("system", "你是{profession}，计算{num1}和{num2}的{operation}。")],
            input_types={"num1": int, "num2": int}  # 限制 num1/num2 为整数
        )
        try:
            await template_with_types.aformat_messages(
                profession="数学家", num1="十", num2=20, operation="加法"
            )
        except Exception as e2:
            print(f"场景2 加类型限制后报错（预期）：{e2}")



# 示例 4：混合消息模板类型
# 1. 定义混合类型的模板（含 BaseMessage、MessagePromptTemplate）
from langchain_core.prompts import SystemMessagePromptTemplate

template = ChatPromptTemplate([
    SystemMessagePromptTemplate.from_template("你是{name}，{description}"),  # SystemMessagePromptTemplate
    HumanMessage(content="我想了解{topic}，能讲一下吗？"),  # 固定 HumanMessage
    ("ai", "好的！{topic}的核心是{core_point}。"),  # 元组格式（AI 消息）
])

# 2. 异步测试：复杂模板格式化
async def test_mixed_templates():
    print("\n=== 示例4：混合消息模板 ===")
    messages = await template.aformat_messages(
        name="科普达人",
        description="用通俗语言讲解科学知识",
        topic="光合作用",
        core_point="植物利用阳光制造有机物"
    )
    for i, msg in enumerate(messages):
        print(f"  消息{i+1}：{type(msg).__name__} -> {msg.content}")

if __name__ == '__main__': 
    # 运行异步函数
    # asyncio.run(test_basic())
    # asyncio.run(test_optional_placeholder())
    # asyncio.run(test_error_cases())
    asyncio.run(test_mixed_templates())

